package br.com.cicero.ed.listasligadas;

public class ListaLigada {
	
	private Celula primeira;
	private Celula ultima;
	private int totalDeElementos;
	
	public void adiciona(Object elemento){
		
		if (totalDeElementos == 0) {
			adicionaNoComeco(elemento);
		} else {
			Celula nova = new Celula(elemento);
			ultima.setProxima(nova);
			nova.setAnterior(ultima);
			ultima = nova;
			totalDeElementos++;
		}
		
	}
	
	public void adiciona(int posicao, Object elemento) {
		
		if (posicao == 0) {
			adicionaNoComeco(elemento);
		} else if (posicao == totalDeElementos) {
			adiciona(elemento);
		} else {
			Celula anterior = pegaCelula(posicao - 1);
			Celula proxima = anterior.getProxima();
			Celula nova = new Celula(anterior.getProxima(), elemento);
			nova.setAnterior(anterior);
			anterior.setProxima(nova);
			proxima.setAnterior(nova);
			totalDeElementos++;
		}
	}
	
	public Object pega(int posicao) {
		return pegaCelula(posicao).getElemento();
	}
	
	public Celula pegaCelula(int posicao) {
		
		if (!posicaoOcupada(posicao)) {
			throw new IllegalArgumentException("Posição não existe");
		}
		
		Celula atual = primeira;
		for (int i = 0; i < posicao; i++) {
			atual = atual.getProxima();
		}
		
		return atual;
	}
	
	public void remove(int posicao) {
		
		if (!posicaoOcupada(posicao)) {
			throw new IllegalArgumentException("Posição não existe");
		} 
		
		if (posicao == 0) {
			removeDoComeco();
		} else if (posicao == totalDeElementos -1) {
			removeDoFim();
		} else {
			Celula anterior = pegaCelula(posicao - 1);
			Celula atual = anterior.getProxima();
			Celula proxima = atual.getProxima();
			
			anterior.setProxima(proxima);
			proxima.setAnterior(anterior);
			
			totalDeElementos--;
		}
		
	}
	
	public int tamanho() {
		return totalDeElementos;
	}
	
	public boolean contem(Object elemento) {
		
		Celula atual = primeira;
		
		while (atual != null) {
			if (atual.getElemento().equals(elemento)) {
				return true;
			}
			atual = atual.getProxima();
		}
		
		return false;
	}
	
	public void adicionaNoComeco(Object elemento) {
		
		if (totalDeElementos == 0) {
			Celula nova = new Celula(elemento);
			primeira = nova;
			ultima = nova;
		} else {
			Celula nova = new Celula(primeira, elemento);
			primeira.setAnterior(nova);
			primeira = nova;
		}
		
		totalDeElementos++;
	}
		
	public void removeDoComeco() {
		
		if (!posicaoOcupada(0)) {
			throw new IllegalArgumentException("Posição não existe");
		}
		
		primeira = primeira.getProxima();
		totalDeElementos--;
		
		if (totalDeElementos == 0) {
			ultima = null;
		}
	}
	
	public void removeDoFim() {
		
		if (!this.posicaoOcupada(totalDeElementos - 1)) {
			throw new IllegalArgumentException("Posição não existe");
		}
		
		if (totalDeElementos == 1) {
			removeDoComeco();
		} else {
			Celula penultima = ultima.getAnterior();
			penultima.setProxima(null);
			ultima = penultima;
			totalDeElementos--;
		}
		
	}
	
	public boolean posicaoOcupada(int posicao) {
		return posicao >= 0 && posicao < totalDeElementos;
	}
	
	public String toString() {
		
		if (totalDeElementos == 0) {
			return "[]";
		}
		
		StringBuilder builder = new StringBuilder("[");
		Celula atual = primeira;
		
		for (int i = 0; i < totalDeElementos - 1; i++) {
			builder.append(atual.getElemento());
			builder.append(", ");
			atual = atual.getProxima();
		}
		
		builder.append(atual.getElemento());
		builder.append("]");
		
		return builder.toString();
	}


}
